package com.yxsk.relay.job.component.common.utils;

import lombok.experimental.UtilityClass;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

@UtilityClass
public class CompressUtils {

    private static final int BUFFER_SIZE = 256;

    public byte[] compress(byte[] source) throws IOException {
        return compress(source, CompressType.GZIP);
    }

    public byte[] compress(byte[] source, CompressType type) throws IOException {
        Assert.notNull(type, "Compress not be null");
        switch (type) {
            case GZIP:
                return gzipCompress(source);
            default:
                throw new IllegalArgumentException("Unsupported compression type");
        }
    }

    public byte[] uncompress(byte[] compressBytes, CompressType type) throws IOException {
        Assert.notNull(type, "Compress not be null");
        switch (type) {
            case GZIP:
                return gzipUncompress(compressBytes);
            default:
                throw new IllegalArgumentException("Unsupported compression type");
        }
    }

    private byte[] gzipCompress(byte[] source) throws IOException {
        if (source == null || source.length == 0) {
            return source;
        }
        // 创建一个新的 byte 数组输出流
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        // 使用默认缓冲区大小创建新的输出流
        try (GZIPOutputStream gzip = new GZIPOutputStream(out)) {
            gzip.write(source);
            gzip.finish();
            return out.toByteArray();
        }
    }

    private byte[] gzipUncompress(byte[] compressBytes) throws IOException {
        if (null == compressBytes || compressBytes.length == 0) {
            return compressBytes;
        }
        // 创建一个新的 byte 数组输出流
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        // 创建一个 ByteArrayInputStream，使用 buf 作为其缓冲区数组
        ByteArrayInputStream in = new ByteArrayInputStream(compressBytes);
        // 使用默认缓冲区大小创建新的输入流
        try (GZIPInputStream gzip = new GZIPInputStream(in)) {
            byte[] buffer = new byte[BUFFER_SIZE];
            int offset = 0;
            while ((offset = gzip.read(buffer)) >= 0) {// 将未压缩数据读入字节数组
                // 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此 byte数组输出流
                out.write(buffer, 0, offset);
            }
            out.flush();
            return out.toByteArray();
        }
    }

    public enum CompressType {
        GZIP
    }

}
